use crate::entities::brand;
use crate::entities::brand_translation;
use crate::errors::AppError;
use sea_orm::*;
use uuid::Uuid;

pub struct BrandService;

impl BrandService {
    pub async fn find_all_brands(
        db: &DatabaseConnection,
        language_code: Option<&str>,
    ) -> Result<Vec<brand::Model>, AppError> {
        if let Some(lang) = language_code {
            let brands = brand::Entity::find()
                .find_with_related(brand_translation::Entity)
                .filter(brand_translation::Column::LanguageCode.eq(lang))
                .all(db)
                .await?;
            Ok(brands.into_iter().map(|(brand, _)| brand).collect())
        } else {
            let brands = brand::Entity::find().all(db).await?;
            Ok(brands)
        }
    }

    pub async fn find_brand_by_id(
        db: &DatabaseConnection,
        id: Uuid,
        language_code: Option<&str>,
    ) -> Result<Option<(brand::Model, Option<brand_translation::Model>)>, AppError> {
        if let Some(lang) = language_code {
            let result = brand::Entity::find_by_id(id)
                .find_with_related(brand_translation::Entity)
                .filter(brand_translation::Column::LanguageCode.eq(lang))
                .all(db)
                .await?;
            if let Some((brand, translations)) = result.into_iter().next() {
                Ok(Some((brand, translations.into_iter().next())))
            } else {
                Ok(None)
            }
        } else {
            let brand = brand::Entity::find_by_id(id).one(db).await?;
            Ok(brand.map(|b| (b, None)))
        }
    }

    pub async fn create_brand(
        db: &DatabaseConnection,
        brand_data: brand::ActiveModel,
    ) -> Result<brand::Model, AppError> {
        let brand = brand_data.insert(db).await?;
        Ok(brand)
    }

    pub async fn update_brand(
        db: &DatabaseConnection,
        id: Uuid,
        brand_data: brand::ActiveModel,
    ) -> Result<Option<brand::Model>, AppError> {
        // First check if the brand exists
        let existing = brand::Entity::find_by_id(id).one(db).await?;
        if existing.is_none() {
            return Ok(None);
        }
        
        // Update the brand
        let brand = brand_data.update(db).await?;
        Ok(Some(brand))
    }

    pub async fn delete_brand(
        db: &DatabaseConnection,
        id: Uuid,
    ) -> Result<bool, AppError> {
        let result = brand::Entity::delete_by_id(id).exec(db).await?;
        Ok(result.rows_affected > 0)
    }

    pub async fn create_brand_translation(
        db: &DatabaseConnection,
        translation_data: brand_translation::ActiveModel,
    ) -> Result<brand_translation::Model, AppError> {
        let translation = translation_data.insert(db).await?;
        Ok(translation)
    }

    pub async fn update_brand_translation(
        db: &DatabaseConnection,
        id: Uuid,
        translation_data: brand_translation::ActiveModel,
    ) -> Result<Option<brand_translation::Model>, AppError> {
        // First check if the translation exists
        let existing = brand_translation::Entity::find_by_id(id).one(db).await?;
        if existing.is_none() {
            return Ok(None);
        }
        
        // Update the translation
        let translation = translation_data.update(db).await?;
        Ok(Some(translation))
    }

    pub async fn delete_brand_translation(
        db: &DatabaseConnection,
        id: Uuid,
    ) -> Result<bool, AppError> {
        let result = brand_translation::Entity::delete_by_id(id).exec(db).await?;
        Ok(result.rows_affected > 0)
    }

    pub async fn list_active(
        db: &DatabaseConnection,
        language_code: Option<&str>,
    ) -> Result<Vec<crate::models::Brand>, AppError> {
        let brands = Self::find_all_brands(db, language_code).await?;
        Ok(brands.into_iter().map(|brand| crate::models::Brand {
            id: brand.id,
            logo_url: brand.logo_url,
            website_url: brand.website_url,
            translations: vec![], // Will be populated by a separate query if needed
        }).collect())
    }
}